<?php

namespace App\Services;

use Illuminate\Support\Facades\Log;

require_once 'Aop/AopClient.php';
require_once 'Aop/AopCertification.php';
require_once 'Aop/request/AlipayTradeQueryRequest.php';
require_once 'Aop/request/AlipayTradeWapPayRequest.php';
require_once 'Aop/request/AlipayTradeAppPayRequest.php';

class AlipayPayment
{
    private $app_id = '';

    private $alipay_cert = 'cert/alipay/alipayCertPublicKey_RSA2.crt';

    private $alipay_root_cert = 'cert/alipay/alipayRootCert.crt';

    private $app_cert = 'cert/alipay/appCertPublicKey_2021002123625026.crt';

    private $private_key = '';

    public  $notify = '';

    public $client;

    public function __construct()
    {
        $aop = new \AopCertClient();


        $aop->gatewayUrl = 'https://openapi.alipay.com/gateway.do';
        $aop->appId = $this->app_id;
        $aop->rsaPrivateKey = $this->private_key;
        $aop->apiVersion = '1.0';
        $aop->signType = 'RSA2';
        $aop->postCharset = 'utf-8';
        $aop->format = 'json';
        $aop->encryptKey = 'CINbfblcSz0IrWqHbMedwQ==';

        //调用getPublicKey从支付宝公钥证书中提取公钥
        $aop->alipayrsaPublicKey = $aop->getPublicKey(storage_path($this->alipay_cert));
        //是否校验自动下载的支付宝公钥证书，如果开启校验要保证支付宝根证书在有效期内
        $aop->isCheckAlipayPublicCert = true;
        //调用getCertSN获取证书序列号
        $aop->appCertSN = $aop->getCertSN(storage_path($this->app_cert));
        //调用getRootCertSN获取支付宝根证书序列号
        $aop->alipayRootCertSN = $aop->getRootCertSN(storage_path($this->alipay_root_cert));

        $this->client = $aop;
    }

    /**
     * 返回实体
     * @return AlipayPayment
     */
    public static function entity()
    {
        return new AlipayPayment();
    }

    /**
     * 返回免密授权url
     * @param string $auth_code
     * @param string $url
     * @return string
     */
    public static function permissions(string $auth_code, string $url)
    {
        $aop = new AlipayPayment();

        $params = [
            'personal_product_code' => 'GENERAL_WITHHOLDING_P',
            'sign_scene'            => 'INDUSTRY|SUPERMARKET',
            'access_params'         => [
                'channel'   => 'ALIPAYAPP',
            ],
            'external_agreement_no' => $auth_code,
            'merchant_process_url'  => $url
        ];

        $request = new \AlipayUserAgreementPageSignRequest();
        $request->setNotifyUrl(config('app.url').$aop->notify.'Auth');
        $request->setBizContent(json_encode($params));

        return 'alipays://platformapi/startapp?'.http_build_query([
                'appId'         => '60000157',
                'appClearTop'   => 'false',
                'startMultApp'  => 'YES',
                'sign_params'   => $aop->client->sdkExecute($request)
            ]);
    }

    /**
     * 换取用户ID
     * @param string $code
     * @return mixed
     * @throws \Exception
     */
    public static function authToken(string $code = '')
    {
        $request = new \AlipaySystemOauthTokenRequest();
        $request->setGrantType('authorization_code');
        $request->setCode($code);

        return self::response($request);
    }

    /**
     * 获取用户授权URL
     * @param string $index
     * @param string $scope
     * @return string
     */
    public static function authUrl(string $index, string $scope = 'auth_base'): string
    {
        return 'https://openauth.alipay.com/oauth2/publicAppAuthorize.htm?'.http_build_query([
                'app_id'    => self::entity()->app_id,
                'scope'     => $scope,
                'redirect_uri'  => config('app.url').$index,
            ]);
    }

    /**
     * 查询免密授权状态
     * @param string $code
     * @return mixed
     * @throws \Exception
     */
    public static function queryAgreement(string $code)
    {
        $request = new \AlipayUserAgreementQueryRequest();
        $request->setBizContent(json_encode([
            'agreement_no'  => $code
        ]));

        return self::response($request);
    }

    /**
     * 验签
     * @param array $data
     * @return bool
     */
    public static function checkSign(array $data)
    {

        return self::entity()
                ->client->rsaCheckV1(
                    $data,
                    storage_path(self::entity()->alipay_cert),
                    $data['sign_type']
            );
    }

    /**
     * 免密扣款
     * @param array $data
     * @return mixed
     * @throws \Exception
     */
    public static function tradePay(array $data)
    {
        $request = new \AlipayTradePayRequest();
        $request->setNotifyUrl(config('app.url').self::entity()->notify);
        $request->setBizContent(json_encode($data));

        return self::response($request);
    }

    /**
     * 交易查询
     * @param string $out_trade_no
     */
    public static function queryOrder(string $out_trade_no)
    {
        $request = new \AlipayTradeQueryRequest();
        $request->setBizContent(json_encode([
            'out_trade_no'  => $out_trade_no,
        ]));

        return self::response($request);
    }

    /**
     * 退款
     * @param string $trade_no
     * @param float $price
     * @param string $order_id
     * @return mixed
     * @throws \Exception
     */
    public static function refund(string $trade_no,float $price,string $order_id)
    {
        $request = new \AlipayTradeRefundRequest();
        $request->setBizContent(json_encode([
            'trade_no'      => $order_id,
            'refund_amount' => $price,
            'out_request_no'=> $trade_no,
        ]));

        return self::response($request);
    }

    /**
     * 企业转账
     * @param string $order_id
     * @param string $mobile
     * @param string $name
     * @param float $price
     * @param string $title
     * @param string $remark
     * @return mixed
     * @throws \Exception
     */
    public static function transfer(string $order_id,string $mobile, string $name, float $price, string $title, string $remark = '')
    {
        $request = new \AlipayFundTransUniTransferRequest();
        $request->setBizContent(json_encode([
            'out_biz_no'    => $order_id,
            'trans_amount'  => $price,
            'product_code'  => 'TRANS_ACCOUNT_NO_PWD',
            'biz_scene'     => 'DIRECT_TRANSFER',
            'order_title'   => $title,
            'remark'        => $remark,
            'payee_info'    => [
                'identity'      => $mobile,
                'identity_type' => 'ALIPAY_LOGON_ID',
                'name'          => $name
            ],
        ]));

        return self::response($request);
    }

    public static function response($request,$type = '')
    {
        $aop = new AlipayPayment();

        if ($type == 'sdk'){
            $result = $aop->client->sdkExecute($request);
        }elseif ($type == 'page'){
            $result = $aop->client->pageExecute($request);
        }else{
            $result = $aop->client->execute($request);
        }
        $responseNode = str_replace(".", "_", $request->getApiMethodName()) . "_response";

        if (isset($result->error_response)) return $result->error_response;

        try {

            return $result->$responseNode;
        }catch (\Exception $exception){
            Log::error('支付宝sdk接口调用失败：'.json_encode($result));
            throw new \Exception('支付宝接口调用异常');
        }
    }





}
